package com.dingwen.treasure.base.convert.model.impl;

import cn.hutool.core.util.StrUtil;
import com.dingwen.treasure.base.convert.model.BeanConvert;
import com.dingwen.treasure.base.exception.BeanConvertException;
import com.dingwen.treasure.base.util.BeanUtil;
import com.dingwen.treasure.base.util.ReflectUtil;
import lombok.SneakyThrows;
import org.springframework.util.ObjectUtils;

import java.util.concurrent.atomic.AtomicBoolean;

/**
 * 　AbstractBeanConvertImpl
 * 　@author dingwen
 * 　@date 2022/5/17
 */
public abstract class AbstractBeanConvertImpl<P, D, V> implements BeanConvert<P, D, V> {

    /**
     * 默认不支持的Bean转化
     */
    private static final String UNSUPPORTED_OPERATION = "默认不支持{}到{}的转换，请自行实现";

    /**
     * 初始化表示： 乐观锁实现多线程条件下初始化方法仅执行一次
     */
    private static final AtomicBoolean ATOMIC_BOOLEAN = new AtomicBoolean(Boolean.FALSE);

    /**
     * 泛型P字节码
     */
    private Class<P> pClass;
    private String pName;


    /**
     * 泛型D字节码
     */
    private Class<D> dClass;
    private String dName;

    /**
     * 泛型V字节码
     */
    private Class<V> vClass;
    private String vName;

    /**
     * 初始化泛型字节码
     */
    public void initClass() {

        if (!ATOMIC_BOOLEAN.compareAndSet(Boolean.FALSE, Boolean.TRUE)
                && !ObjectUtils.isEmpty(pClass)
                && !ObjectUtils.isEmpty(dClass)
                && !ObjectUtils.isEmpty(vClass)
        ) {
            //已经完成初始化
            return;
        }

        // 持久化对象信息
        pClass = ReflectUtil.getClassForGeneric(0, this);
        pName = pClass.getName();

        // 数据传输对象信息
        dClass = ReflectUtil.getClassForGeneric(1, this);
        dName = dClass.getName();

        // 视图对象信息
        vClass = ReflectUtil.getClassForGeneric(2, this);
        vName = vClass.getName();

    }

    /**
     * PO ---> DTO
     * 持久化对象 ---> 数据传输对象
     *
     * @param p P
     * @return {@link D}
     */
    @Override
    public D poToDto(P p) {
        initClass();
        String message = StrUtil.format(UNSUPPORTED_OPERATION, pName, dName);
        throw new BeanConvertException(message);
    }

    /**
     * PO ---> VO
     * 持久化对象 ---> 视图对象
     *
     * @param p P
     * @return {@link V}
     */
    @Override
    @SneakyThrows(Throwable.class)
    public V poToVo(P p) {
        initClass();
        return BeanUtil.copyProperties(p, vClass);
    }

    /**
     * DTO ---> PO
     * 数据传输对象 ---> 持久化对象
     *
     * @param d D
     * @return {@link P}
     */
    @Override
    @SneakyThrows(Throwable.class)
    public P dtoToPo(D d) {
        initClass();
        return BeanUtil.copyProperties(d, pClass);
    }

    /**
     * DTO ---> VO
     * 数据传输对象 ---> 视图对象
     *
     * @param d D
     * @return {@link P}
     */
    @Override
    public V dtoToVo(D d) {
        initClass();
        String message = StrUtil.format(UNSUPPORTED_OPERATION, dName, vName);
        throw new BeanConvertException(message);
    }

    /**
     * VO ---> PO
     * 视图对象 ---> 持久化对象
     *
     * @param v
     * @return {@link P}
     */
    @Override
    public P voToPo(V v) {
        initClass();
        String message = StrUtil.format(UNSUPPORTED_OPERATION, vName, pName);
        throw new BeanConvertException(message);
    }

    /**
     * VO ---> DTO
     * 视图对象 ---> 数据传输对象
     *
     * @param v
     * @return {@link P}
     */
    @Override
    public D voToDto(V v) {
        initClass();
        String message = StrUtil.format(UNSUPPORTED_OPERATION, vName, dName);
        throw new BeanConvertException(message);
    }


}
